#include <iostream>
#include <Eigen/Dense>
#include "mymodel.h"
#include "nn_layer.h"

using namespace std;

#define pic_size 28
#define train_size 2000
#define test_size 2000
#define batch_size 100
#define num_labels 10
#define epoch 200
#define kernel_size 4
#define kernel_nums 8
#define stride 2


int main()
{
	typedef Eigen::MatrixXd mat;
	Eigen::MatrixXd train_images(train_size, pic_size * pic_size),
		one_hot_train_labels(train_size, num_labels),
		test_images(test_size, pic_size * pic_size);
	Eigen::VectorXd test_labels(test_size), train_labels(train_size);
	
	//load data from txt and execute one hot code
	load_data(train_images, train_labels, "train_images.txt", "train_labels.txt");
	load_data(test_images,test_labels, "test_images.txt","test_labels.txt");
	one_hot_train_labels = one_hot(num_labels, train_labels);

	//construct a model and add layers
	//train
	mymodel model;

	//original
	//model.add(layer(100, "relu", pic_size * pic_size));
	//model.add(layer(10, "softmax"));

	//better
	model.combine_template(cnn_layer(kernel_size, kernel_size, kernel_nums, stride, pic_size, pic_size, "tanh"), layer(10, "softmax"));
	
	//initialization
	model.init();

	//set up compile parms: learning rate, dropout and loss_func
	model.compile(0.05, 0.5 ,0);

	model.describe();

	//execute fp and bp on train sets
	model.fit(train_images, one_hot_train_labels, epoch, batch_size, test_images, test_labels);
	
	//model.file_export();

	//test, using this as an example
	//these files has stored params for layers and weight
	/*mymodel model;
	model.file_input("cnnlayerfile1.txt", "fulllayerfile2.txt");
	model.test();*/

	return 0;
}